#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include "campo.h"
#include "jogador.h"
#include "util.h"

Jogador criarComputador();
Pos jogarComputador(Campo);
Pos casaMaiorProbabilidadeBombasAoRedor(Campo, double*);
int podeTerBomba(Campo, Pos);
int qtdPossiveisBombasAdjacentes(Campo, Pos);
Pos possivelBombaAdjacente(Campo, Pos);
Pos chuteRandomico(Campo);

Jogador criarComputador() {
	Jogador computador = { .nome = "Computador", .jogar = &jogarComputador,
			.casaBomba = bombaComputador };
	return computador;
}

Pos jogarComputador(Campo campo) {
	double probabilidade;

	Pos posMaiorProbabilidade = casaMaiorProbabilidadeBombasAoRedor(campo, &probabilidade);

	if(probabilidade == 0)
		return chuteRandomico(campo);

	return possivelBombaAdjacente(campo, posMaiorProbabilidade);
}

int qtdPossiveisBombasAdjacentes(Campo campo, Pos posAtual) {
	Pos posAdjacente;
	int possiveisBombas = 0;

	posAdjacente.m = posAtual.m - 1;
	for (posAdjacente.n = posAtual.n - 1; posAdjacente.n <= posAtual.n + 1; posAdjacente.n++) {
		if (podeTerBomba(campo, posAdjacente))
			possiveisBombas++;
	}

	posAdjacente.m = posAtual.m + 1;
	for (posAdjacente.n = posAtual.n - 1; posAdjacente.n <= posAtual.n + 1; posAdjacente.n++) {
		if (podeTerBomba(campo, posAdjacente))
			possiveisBombas++;
	}

	posAdjacente.m = posAtual.m;
	posAdjacente.n = posAtual.n - 1;
	if (podeTerBomba(campo, posAdjacente))
		possiveisBombas++;

	posAdjacente.n = posAtual.n + 1;
	if (podeTerBomba(campo, posAdjacente))
		possiveisBombas++;

	return possiveisBombas;
}

Pos possivelBombaAdjacente(Campo campo, Pos posAtual) {
	Pos posAdjacente;

	posAdjacente.m = posAtual.m - 1;
	for (posAdjacente.n = posAtual.n - 1; posAdjacente.n <= posAtual.n + 1; posAdjacente.n++) {
		if (podeTerBomba(campo, posAdjacente))
			return posAdjacente;
	}

	posAdjacente.m = posAtual.m + 1;
	for (posAdjacente.n = posAtual.n - 1; posAdjacente.n <= posAtual.n + 1; posAdjacente.n++) {
		if (podeTerBomba(campo, posAdjacente))
			return posAdjacente;
	}

	posAdjacente.m = posAtual.m;
	posAdjacente.n = posAtual.n - 1;
	if (podeTerBomba(campo, posAdjacente))
		return posAdjacente;

	posAdjacente.n = posAtual.n + 1;
	return posAdjacente;
}

Pos chuteRandomico(Campo campo) {
	Pos pos;
	do {
		pos.m = (int) (((double) rand() / RAND_MAX) * (campo.tamanho - 1));
		pos.n = (int) (((double) rand() / RAND_MAX) * (campo.tamanho - 1));
	} while (!podeTerBomba(campo, pos));
	return pos;
}

Pos casaMaiorProbabilidadeBombasAoRedor(Campo campo, double *maiorProbabilidade) {
	Pos posAtual;
	Casa * casaAtual;
	Pos posMaiorValor = {-1, -1};
	*maiorProbabilidade = 0;
	double probDeHaverBomba;
	for (posAtual.m = 0; posAtual.m < campo.tamanho; posAtual.m++) {
		for (posAtual.n = 0; posAtual.n < campo.tamanho; posAtual.n++) {
			casaAtual = getCasa(campo, posAtual);
			if (casaAtual->visivel && ehNumero(casaAtual->tipoCasa)
					&& ((probDeHaverBomba = (double) bombasFechadasAoRedor(
							casaAtual, posAtual, campo)
							/ qtdPossiveisBombasAdjacentes(campo, posAtual)) > 0)
					&& (probDeHaverBomba > *maiorProbabilidade)) {
				*maiorProbabilidade = probDeHaverBomba;
				if(*maiorProbabilidade == 1)
					return posAtual;
				posMaiorValor = posAtual;
			}
		}
	}
	return posMaiorValor;
}

int podeTerBomba(Campo campo, Pos pos) {
	Casa * casaAtual = getCasa(campo, pos);
	if (casaAtual->visivel) {
		return 0;
	}
	Pos posAdjacente;
	Casa * casaAdjacente;
	for (posAdjacente.n = pos.n - 1; posAdjacente.n <= pos.n + 1; posAdjacente.n++) {
		posAdjacente.m = pos.m - 1;
		casaAdjacente = getCasa(campo, posAdjacente);
		if (ehNumero(casaAdjacente->tipoCasa) && !bombasFechadasAoRedor(
				casaAdjacente, posAdjacente, campo)) {
			return 0;
		}
		posAdjacente.m = pos.m + 1;
		casaAdjacente = getCasa(campo, posAdjacente);
		if (ehNumero(casaAdjacente->tipoCasa) && !bombasFechadasAoRedor(
				casaAdjacente, posAdjacente, campo)) {
			return 0;
		}
	}

	posAdjacente.m = pos.m;
	posAdjacente.n = pos.n - 1;
	casaAdjacente = getCasa(campo, posAdjacente);
	if (ehNumero(casaAdjacente->tipoCasa) && !bombasFechadasAoRedor(
			casaAdjacente, posAdjacente, campo)) {
		return 0;
	}

	posAdjacente.n = pos.n + 1;
	casaAdjacente = getCasa(campo, posAdjacente);
	if (ehNumero(casaAdjacente->tipoCasa) && !bombasFechadasAoRedor(
			casaAdjacente, posAdjacente, campo)) {
		return 0;
	}

	return 1;
}
